/*
 *2024-02-07
 * 局平台爬虫软件
 *
 *
 *
 * 
 *
 *
 *
 *
 *
 */
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <openssl/sha.h>
#include <zlib.h>
#include <mysql.h>
#include "cJSON/cJSON.h"
#include "data_type.h"
#include "myfunc.h"

//*******************************************************************************
//	局平台登陆用户名及密码
//*******************************************************************************
#define LOGIN_NAME "xianxueyun"
#define LOGIN_PWD  "2023jcjf"
//********************************************************************************
//	mysql 数据库连接
//********************************************************************************
#define MYSQL_DB_NAME 		"test_db"
#define MYSQL_SERVER_IP 	"localhost"
#define MYSQL_USR_NAME		"kimi"
#define MYSQL_USR_PWD		"123abc//"
#define MYSQL_SERVER_PORT 	3306

//***********websocket缓存区大小*********
#define WS_DATA_BUF_SIZE 16384
//***********压缩后的发送数据************
//const unsigned char WS_SEND_DATA_1[] = {
//	0x8a, 0x56, 0x72, 0xf6, 0xf7, 0xf3, 0x73, 0x75, 0x0e, 0x89, 0xc9, 0x4b,
//	0x2e, 0x2d, 0x2a, 0x4a, 0xcd, 0x2b, 0x09, 0x2d, 0x4e, 0x2d, 0xf2, 0x4c,
//	0xb1, 0x32, 0x34, 0x36, 0x37, 0x8e, 0xc9, 0x4b, 0x4c, 0x4e, 0x4e, 0x2d,
//	0x28, 0xd1, 0x2d, 0x4b, 0x2d, 0x2a, 0xce, 0xcc, 0xcf, 0xb3, 0x32, 0xd4,
//	0x33, 0xd4, 0x31, 0xd4, 0x33, 0x88, 0xc9, 0xcb, 0x48, 0x4d, 0x2c, 0x2a,
//	0xd1, 0x4d, 0x4a, 0x4d, 0x2c, 0xb1, 0x32, 0x34, 0x00, 0x02, 0x1d, 0x30,
//	0x19, 0x93, 0x07, 0x84, 0xa5, 0x20, 0x96, 0x52, 0x2c, 0x00
//};

//**********发送给websocket服务器的明文******************************************
const unsigned char WS_SEND_DATA_1[]="[\"CONNECT\\ncurrentUserId:1373\\n"
	"accept-version:1.1,1.0\\nheart-beat:10000,10000\\n\\n\\u0000\"]";

const unsigned char WS_SEND_DATA_2[]="[\"SUBSCRIBE\\nid:sub-6\\ndestination:"
	"/topic/oprtOrder\\n\\n\\u0000\"]";

//**********zlib 压缩尾巴********************************************************
const char ZLIB_DEFLATE_TAIL[4]={0x00,0x00,0xff,0xff};

//***********WS_SEND_DATA_1长度
//const unsigned int ws_send_data_1_len = 82;


//********************************************************************************
//		全局变量声明
//********************************************************************************
//	调度令详细信息队列,写入数据库后删除
struct order_page_node 	*sys_order_pages;	
//	未读取详细信息的调度令id队列,获取详细信息后删除
struct order_page_node 	*sys_order_id_unread;
//	历史调度令id队列
struct int_queue_node 	*sys_order_id_history;
//	websocket 分割后、解压缩前数据队列
struct ws_data_node *sys_ws_data_queue_deflated;
//	websocket  解压缩后数据队列
struct ws_data_node *sys_ws_data_queue_inflated;
//	存放cookie jsessionid
char jsessionid_ptr[100];	  
//	存放cookie rememberMe
char remember_ptr[1025];	  
//	调度零详细信息队列互斥锁
pthread_mutex_t sys_pages_lock;
//	http线程错误文件互斥锁
pthread_mutex_t error_file_lock;
//	网络状态标志位锁
pthread_mutex_t net_status_lock;		
//	网络状态标志位
bool net_status;				

//******************************************************************************
//			主函数
//******************************************************************************

int main(int argc,char* argv[]){
	//**********************************************************************
	// 局部变量、数据结构定义、初始化
	//**********************************************************************
	//	需要初始化/销毁的变量
	//
	CURL *handle;       		  		// libcurl http操作句柄
	CURL *ws_handle;		  		// libcurl ws 操作句柄
	struct curl_slist* request_header;		//http 协议头
	struct data_buffer http_cb_arg,http_hd_cb_arg;	//http 回调函数传入变量
	struct data_buffer ws_db_tmp;	  		// 存储websocket 原始数据临时变量
	//	zlib 变量
	z_stream ws_zs_recv;		  		//zlib 发送 zstream
	z_stream ws_zs_send;		  		//还没用上
	struct data_buffer z_inflate_db;  		//存放临时解压数据
	time_t unix_time;		  		// unix 时间戳
	MYSQL *con;			  		// mysql 句柄
	struct order_page op_tmp;	  		// mysql 临时变量
	struct order_info order_info;	  		//
	//
	//
	//**********************************************************************
	//	无需销毁的变量
	//	
	CURLcode curl_code; 		  		// libcurl 函数返回值
	char url[100];			  		//http请求的url地址
	char cookie_str[100];		  		//存放cookie "usbp-service"
	char auth_random_tmp[100];	  		//http登陆需要的一个参数，存unix timestamp
	char *auth_random_ptr;		  		//authRandom起始位置
	char location_tmp[100];		  		//存放302跳转Location:xxxxxx
	char *location_ptr;		  		//Location起始位置
	char post_data[256];		  		//http post 数据
	//***********websocket 通信部分变量
	const struct curl_ws_frame *meta; 	  	// ws 通信变量返回
	unsigned char ws_char_buffer[WS_DATA_BUF_SIZE];//ws通信接收数据缓存 curl_ws_recv
	size_t ws_data_recv;		  		// ws通信接收的数据数量
	size_t ws_data_send;		  		// ws通信发送的数据数量
	char z_inflate_char_tmp[1024];	  		//存放解压缩后的数据临时变量
	int inflate_init_status;	  		//压缩句柄初始化状态
	int inflate_status;				//解压缩函数返回值
	//***********sha1 计算变量
	char sha1_data[30];				//计算sha的数据
	unsigned char sha1_result[21];	  		//sha 结果 
	unsigned char sha1_result_str[41];		//sha 结果字符串
	int init_try_times;		  		//http/websocket初始化失败尝试次数
	bool net_error_retry;		  		// 
	//***********myslq变量
	MYSQL_RES *query_result;	  		// mysql 结果
	MYSQL_ROW row_data;		  		// mysql 列数据
	long tb_order_id;		  		// mysql 临时变量
	char sql_stat[1024];		  		// mysql 语句
	int query_status;		  		// mysql 查询语句返回值
	int row_number;			  		// mysql 结果列数
	int db_reconnect_times;		  		// 重连次数
	size_t json_str_len;				//json数据长度
	char *json_str_begin;				//json数据开始的地址
	char *json_str_ptr;				//存放转义后的json数据
	bool sys_order_pages_empty;			//全局变量调度令队列空标志
	//**********************************************************************************
	//
	//**********************************************************************************
	//	全局变量初始化
	//**********************************************************************************
	curl_code=curl_global_init(CURL_GLOBAL_ALL);	    //libcurl环境初始化 only once
	sys_order_pages=	order_pages_init();	    //调度令信息队列初始化
	sys_order_id_unread=	order_pages_init();	    //未读取信息队列初始化
	sys_order_id_history=int_queue_init();		    //已读取详细信心的调度令id队列
	sys_ws_data_queue_deflated=ws_data_queue_init();    //初始化解压缩前数据队列
	sys_ws_data_queue_inflated=ws_data_queue_init();    //初始化解压缩后数据队列
	pthread_mutex_init(&sys_pages_lock,NULL);	    //初始化共享锁
	pthread_mutex_init(&error_file_lock,NULL);	    //初始化共享锁
	pthread_mutex_init(&net_status_lock,NULL);	    //初始化共享锁
	memset(jsessionid_ptr,0,100);
	memset(remember_ptr,0,1025);
	//*****************************************************************************************
	//	局部变量初始化
	//*****************************************************************************************
	data_buffer_init_1k(&http_cb_arg);
	data_buffer_init_1k(&http_hd_cb_arg);
	data_buffer_init_16k(&ws_db_tmp);	//初始化ws通信接收数据缓存
	data_buffer_init_16k(&z_inflate_db);
	json_str_len=0;				//json数据长度
	json_str_begin=NULL;			//json数据开始的地址
	json_str_ptr=NULL;			//存放转义后的json数据
	sys_order_pages_empty=true;
SYS_START:
	//*********************************************************************************************
	//	http 初始化,设置回调函数
	//*********************************************************************************************
	data_buffer_reset_1k(&http_cb_arg);
	data_buffer_reset_1k(&http_hd_cb_arg);
	data_buffer_reset_16k(&ws_db_tmp);	//初始化ws通信接收数据缓存
	data_buffer_reset_16k(&z_inflate_db);
	json_str_len=0;				//json数据长度
	json_str_begin=NULL;			//json数据开始的地址
	json_str_ptr=NULL;			//存放转义后的json数据
	sys_order_pages_empty=true;
	handle=curl_easy_init();
	ws_handle=curl_easy_init();
	net_error_retry=false;
	request_header=NULL;
	pthread_mutex_lock(&net_status_lock);
	net_status=false;
	pthread_mutex_unlock(&net_status_lock);
	do{
	//*************************************************************************************
	//	循环初始化直至初始化成功
	//*************************************************************************************
sleep(2);
		printf("开始初始化\n");
		printf("发送http1请求\n");
		//	网络故障情况下间隔重连
		if(net_error_retry){sleep(10);}
		memset(jsessionid_ptr,0,100);
		memset(remember_ptr,0,1025);
		memset(cookie_str,0,100);		 
		memset(auth_random_tmp,0,100);	  	
		auth_random_ptr=NULL;
		memset(location_tmp,0,100);
		location_ptr=NULL;		  	  
		//*************************************************************************************
		//		http request 1
		//*************************************************************************************
		time(&unix_time);	//返回自1970.1.1 0:0:0至今的秒数
		sprintf(url,"%s%llu","http://10.5.3.40/auth/api/genLoginPage?"
				"instanceCode=UserPasswordAuth&timestamp=",(long long)unix_time*1000);
		curl_easy_setopt(handle,CURLOPT_URL,url);
		curl_easy_setopt(handle,CURLOPT_HTTPGET,1L);
		curl_easy_setopt(handle,CURLOPT_TIMEOUT,25L);
		curl_easy_setopt(handle,CURLOPT_CONNECTTIMEOUT,15L);
		//*********** http header 信息
		curl_slist_free_all(request_header);
		request_header=NULL;
		request_header=curl_slist_append(request_header,"Accept: */*");
		request_header=curl_slist_append(request_header,"User-Agent: Dalaodaidaiwo/1.0");
		request_header=curl_slist_append(request_header,"Connection: keep-alive");
		curl_easy_setopt(handle,CURLOPT_HTTPHEADER,request_header);
		//*********** 回调函数、参数
		curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,http_cb_func);
		curl_easy_setopt(handle,CURLOPT_WRITEDATA,&http_cb_arg);
		curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,http_hd_cb_func);
		curl_easy_setopt(handle,CURLOPT_HEADERDATA,&http_hd_cb_arg);
		data_buffer_reset_1k(&http_hd_cb_arg);
		data_buffer_reset_1k(&http_cb_arg);
		curl_code=curl_easy_perform(handle);//模块A 通讯4
		//*********** http 通信异常处理
		if(curl_code!=CURLE_OK){
			printf("http1 error\n");
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			goto HTTP_WS_RETRY;
		}
		//*********** 获取以下两个参数
		if(!regex_find(auth_random_tmp,http_cb_arg.contentPtr,"\"authRandom\":\"[0-9]*")){
			printf("authRandom not found\n");
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			goto HTTP_WS_RETRY;
		}
		if(!regex_find(cookie_str,http_hd_cb_arg.contentPtr,"ubsp-service=[^;]*")){
			printf("cookie :ubsp-service not found\n");
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			goto HTTP_WS_RETRY;	
		}
		//	只需要 "authRandom": 后面的数字
		auth_random_ptr=auth_random_tmp+14;
printf("authRandom:%s\n",auth_random_ptr);
printf("cookie:%s\n",cookie_str);
		//	清空保存http头和http内容的数据结构
		curl_slist_free_all(request_header);
		request_header=NULL;
		data_buffer_reset_1k(&http_hd_cb_arg);
		data_buffer_reset_1k(&http_cb_arg);

sleep(2);
		//*************************************************************************************
		//		http request 2
		//*************************************************************************************
printf("发送http2请求\n");
		sprintf(url,"%s","http://10.5.3.40/auth/api/login");
		curl_easy_setopt(handle,CURLOPT_URL,url);
		curl_easy_setopt(handle,CURLOPT_POST,1L);
		//*********** http header 信息
		curl_slist_free_all(request_header);
		request_header=NULL;
		request_header=curl_slist_append(request_header,"Accept: */*");
		request_header=curl_slist_append(request_header,"User-Agent: Dalaodaidaiwo/1.0");
		request_header=curl_slist_append(request_header,"Connection: keep-alive");
		request_header=curl_slist_append(request_header,"Content-Type: application"
				"/x-www-form-urlencoded");
		curl_easy_setopt(handle,CURLOPT_HTTPHEADER,request_header);
		//		计算post数据中password字段的sha1运算
		curl_easy_setopt(handle,CURLOPT_COOKIE,cookie_str);
		strcpy(sha1_data,LOGIN_PWD);
		strcat(sha1_data,"|");
		strcat(sha1_data,auth_random_ptr);
		SHA1(sha1_data,strlen(sha1_data),sha1_result);
		hex_to_str(sha1_result_str,sha1_result,20);
		sprintf(post_data,"%s%s%s%s%s%s%s","loginName=",LOGIN_NAME,"&password=",\
			sha1_result_str,"&authRandom=",auth_random_ptr,"&captcha=&mac=f56a6b94");
		curl_easy_setopt(handle,CURLOPT_POSTFIELDS,post_data);
		curl_easy_setopt(handle,CURLOPT_POSTFIELDSIZE,strlen(post_data));
		curl_code=curl_easy_perform(handle);
		if(curl_code!=CURLE_OK){
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			printf("http2 error\n");
			goto HTTP_WS_RETRY;
		}
		//		清空http响应数据
		data_buffer_reset_1k(&http_hd_cb_arg);
		data_buffer_reset_1k(&http_cb_arg);
		curl_slist_free_all(request_header);
		request_header=NULL;
sleep(2);
		//*************************************************************************************
		//		http request 3
		//*************************************************************************************
printf("发送http3请求\n");
		sprintf(url,"http://10.5.3.40/sso/JOMSYX");
		curl_easy_setopt(handle,CURLOPT_URL,url);
		curl_easy_setopt(handle,CURLOPT_HTTPGET,1L);
		//*********** http header 信息
		curl_slist_free_all(request_header);
		request_header=NULL;
		request_header=curl_slist_append(request_header,"Accept: */*");
		request_header=curl_slist_append(request_header,"User-Agent: Dalaodaidaiwo/1.0");
		request_header=curl_slist_append(request_header,"Connection: keep-alive");
		curl_easy_setopt(handle,CURLOPT_HTTPHEADER,request_header);
		curl_code=curl_easy_perform(handle);
		if(curl_code!=CURLE_OK){
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			printf("http3 error\n");
			goto HTTP_WS_RETRY;
		}
		if(!regex_find(location_tmp,http_hd_cb_arg.contentPtr,"^Location:[ a-zA-Z0-9:/.?=-]*")){
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			printf("Location error\n");
			goto HTTP_WS_RETRY;
		}
		//	截取'Location: '后的地址
		location_ptr=location_tmp+10;
		//	清空http响应数据
		
		curl_slist_free_all(request_header);
		request_header=NULL;
		data_buffer_reset_1k(&http_hd_cb_arg);
		data_buffer_reset_1k(&http_cb_arg);
sleep(2);
		//*************************************************************************************
		//		http request 4
		//*************************************************************************************
printf("http4\n");
		curl_easy_cleanup(handle);
		handle=curl_easy_init();
		curl_easy_setopt(handle,CURLOPT_HTTPGET,1L);
		curl_easy_setopt(handle,CURLOPT_TIMEOUT,20L);
		curl_easy_setopt(handle,CURLOPT_CONNECTTIMEOUT,10L);
		//*********** http header 信息
		curl_slist_free_all(request_header);
		request_header=NULL;
		request_header=curl_slist_append(request_header,"Accept: */*");
		request_header=curl_slist_append(request_header,"User-Agent: Dalaodaidaiwo/1.0");
		request_header=curl_slist_append(request_header,"Connection: keep-alive");
		curl_easy_setopt(handle,CURLOPT_HTTPHEADER,request_header);
		//*********** 回调函数、参数
		curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,http_cb_func);
		curl_easy_setopt(handle,CURLOPT_WRITEDATA,&http_cb_arg);
		curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,http_hd_cb_func);
		curl_easy_setopt(handle,CURLOPT_HEADERDATA,&http_hd_cb_arg);
		//		访问地址
		curl_easy_setopt(handle,CURLOPT_URL,location_ptr);
		//		go request
		curl_code=curl_easy_perform(handle);
		if(curl_code!=CURLE_OK){
			printf("http4 perform failed\n");
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			goto HTTP_WS_RETRY;
		}
		if(!regex_find(jsessionid_ptr,http_hd_cb_arg.contentPtr,"JSESSIONID=[^;]*?")){
			printf("jessionid error\n");
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			goto HTTP_WS_RETRY;
		}
		if(!regex_find(remember_ptr,http_hd_cb_arg.contentPtr,"rememberMe=[^;]*?")){
			printf("rememver error\n");
			//curl_easy_cleanup(handle);
			curl_slist_free_all(request_header);
			request_header=NULL;
			data_buffer_reset_1k(&http_hd_cb_arg);
			data_buffer_reset_1k(&http_cb_arg);
			goto HTTP_WS_RETRY;
		}
		//***************************************************************************
		//	至此获得jsession_id / rememberMe 两个cookie
		//***************************************************************************
printf("jsessionid :%s\n",jsessionid_ptr);
printf("rememberMe :%s\n",remember_ptr);
		//	清空存储http响应内容的变量
		curl_slist_free_all(request_header);
		request_header=NULL;
		data_buffer_reset_1k(&http_hd_cb_arg);
		data_buffer_reset_1k(&http_cb_arg);

		//*************************************************************************
		//	初始化zlib
		//*************************************************************************
		ws_zs_recv.zalloc=NULL;
		ws_zs_recv.zfree=NULL;
		ws_zs_recv.opaque=NULL;
		//	初始化 raw deflate模式解压 window bit=15
		inflate_init_status=inflateInit2(&ws_zs_recv,-15);
		switch(inflate_init_status){
			case Z_OK:
				printf("inflate init ok\n");
				break;
			case Z_MEM_ERROR:
				printf("zlib error:no enough memory\n");
				break;
			case Z_STREAM_ERROR:
				printf("zlib error:invalid parameter\n");
				break;
			case Z_VERSION_ERROR:
				printf("zlib error:incompatible zlib version\n");
				break;
			default:
				printf("zlib error:error\n");
				break;
		}
		//初始化失败
		if(inflate_init_status!=Z_OK){
			inflateEnd(&ws_zs_recv);
			printf("Zlib init error\n");
			goto HTTP_WS_RETRY;
		}
		printf("zlib init ok\n");
		//初始化成功Z_OK go on



		//**************************************************************************************
		//	websocket 通信初始化
		//**************************************************************************************
		//	Connect_only model
		//By setting CURLOPT_CONNECT_ONLY to 2L, the transfer only establishes and setups 
		//the WebSocket communication and then returns control back to the application.		
		curl_slist_free_all(request_header);
		request_header=NULL;
		//	设置websocket压缩及压缩参数
		request_header=curl_slist_append(request_header,"Sec-WebSocket-Extensions"
			": permessage-deflate; client_max_window_bits");
		curl_easy_setopt(ws_handle,CURLOPT_HTTPHEADER,request_header);
		//	websocket 地址
		curl_easy_setopt(ws_handle,CURLOPT_URL,"ws://10.12.3.23/webSocket/839/3n5dr6r7/websocket");
		curl_easy_setopt(ws_handle,CURLOPT_CONNECT_ONLY,2L);
		curl_code=curl_easy_perform(ws_handle);
		if(curl_code!=CURLE_OK){
			printf("websocket perform failed. Error :%u\n",curl_code);
			curl_slist_free_all(request_header);
			request_header=NULL;
			//curl_easy_cleanup(ws_handle);
			goto HTTP_WS_RETRY;
		}
		printf("websocket connect\n");
		curl_slist_free_all(request_header);
		request_header=NULL;

		//***************************************************************************************
		//	mysql 初始化
		//***************************************************************************************
		db_reconnect_times=6;
		con=mysql_init(NULL);
		while(db_reconnect_times--){
			if( con && mysql_real_connect(con,MYSQL_SERVER_IP,MYSQL_USR_NAME,MYSQL_USR_PWD,\
						MYSQL_DB_NAME,MYSQL_SERVER_PORT,NULL,0) ){
				printf("mysql connect ok\n");
				break;
			}
			else{
				mysql_close(con);
				con=mysql_init(NULL);
			}
		}
		if( db_reconnect_times==-1 ){//初始化失败
			printf("mysql connect failed\n");
			mysql_close(con);
			printf("%s\n",mysql_error(con));
			goto HTTP_WS_RETRY;
		}

		//******************************************************************************
		//	free 一些变量
		//******************************************************************************
		//顺利初始化 跳出该循环
		//网络状态初始化为正常
		pthread_mutex_lock(&net_status_lock);
		net_status=true;
		pthread_mutex_unlock(&net_status_lock);
		break;			
HTTP_WS_RETRY:
		//*******************************************************************************************
		//			重置变量，继续初始化
		//*******************************************************************************************
		//	局部变量
		curl_easy_cleanup(handle);
		handle=curl_easy_init();
		curl_easy_cleanup(ws_handle);
		ws_handle=curl_easy_init();
		curl_slist_free_all(request_header);
		request_header=NULL;
		net_error_retry=true;				//暂停30s
		data_buffer_reset_1k(&http_cb_arg);
		data_buffer_reset_1k(&http_hd_cb_arg);
	}
	while(1);
	

	//***********************************************************************************
	//		!!!!!!!!!初始化成功
	//		循环读取websocket服务器发送的数据
	//	解压缩后提取调度令提醒，从提醒数据里找出新调度令的id
	//	比对是否是历史调度令里的，是：丢弃该数据；否：读取该id详细调度令信息
	//***********************************************************************************
	printf("Start websocket communicate\n");

//******************************************************************************
//	手动输入调度零 调试用
//******************************************************************************
/*
int a=1240624;
struct order_page test;
for(int i=0;i<2;i++){
	a++;
	order_page_init(&test);
	test.tb_order_id=a;
	test.order_year=2024;
	strcpy(test.order_code,"047381");
	strcpy(test.station_id,"91");
	strcpy(test.send_date,"2023-03-14 14:49:50");
	strcpy(test.recv_date,"2023-03-14 14:49:50");
	add_order_pages(sys_order_id_unread,&test);
	order_page_destroy(&test);
}*/

	while(1){
		sleep(1);
		//*************************************************************************************
		//	接受websocket数据，将websocket缓存的数据进行切割，还原出
		//	每个完整的message,压入sys_ws_data_queue_deflated队列
		//*************************************************************************************
		//	开始取websocket数据 缓冲区1k
		data_buffer_reset_16k(&ws_db_tmp);//初始化ws通信接收数据缓存
		curl_code=curl_ws_recv(ws_handle,ws_char_buffer,WS_DATA_BUF_SIZE,\
				&ws_data_recv,&meta);
//printf("curl_code:%u\n",curl_code);
		//	got_nothing 和 again 都不是故障
		//	暂时还不知道故障的返回值??????????????????
		if( curl_code == CURLE_GOT_NOTHING ){	printf("cool ,wo get CURLE_GOT_NOTHING\n");}
		if( curl_code == CURLE_AGAIN ){		printf("cool ,wo get CURLE_AGAIN\n");}
		while(ws_data_recv){//有没有websocket数据?
			//	数据可能不完整,存入ws_db_tmp暂存
			add_data(&ws_db_tmp,ws_char_buffer,ws_data_recv);  //data--->ws_db_tmp
			while(meta->bytesleft){//数据取完整了吗？
				curl_code=curl_ws_recv(ws_handle,ws_char_buffer,\
						WS_DATA_BUF_SIZE,&ws_data_recv,&meta);
				//循环读完一个message,添加到ws_db_tmp
				add_data(&ws_db_tmp,ws_char_buffer,ws_data_recv);//data--->ws_db_tmp
			}
			//压入一个完整数据进入wb解压缩前队列
			add_ws_data(sys_ws_data_queue_deflated,&ws_db_tmp);
			//清空暂存数据结构
			data_buffer_reset_16k(&ws_db_tmp);
			curl_code=curl_ws_recv(ws_handle,ws_char_buffer,WS_DATA_BUF_SIZE,\
					&ws_data_recv,&meta);
		}
		data_buffer_reset_16k(&ws_db_tmp);



		//**********************************************************************************
		//	websocket 数据取空，接下来进行解压
		//	取wb队列数据，对数据进行inflate解压
		//	清空解压缩前数据队列,解压后数据压入sys_ws_data_queue_inflated队列
		//**********************************************************************************
		data_buffer_reset_16k(&z_inflate_db);		//压缩数据输出
		data_buffer_reset_16k(&ws_db_tmp);		//压缩数据输入
		//	将完整数据放入ws_db_tmp数据结构
		//	ws_db_tmp存放一个完整的websocket message
		while(out_ws_data(sys_ws_data_queue_deflated,&ws_db_tmp)){
			//添加  00 00 ff ff 作为结尾才能进行解压缩
			add_data(&ws_db_tmp,ZLIB_DEFLATE_TAIL,4);
			//解压缩初始化,设置待压缩数据地址及大小
			ws_zs_recv.avail_in=ws_db_tmp.dataSize;
			ws_zs_recv.next_in=ws_db_tmp.contentPtr;
			do{
				//设置输出缓冲区
				ws_zs_recv.next_out=z_inflate_char_tmp;
				ws_zs_recv.avail_out=1024;
				inflate_status=inflate(&ws_zs_recv,Z_SYNC_FLUSH);
				if(inflate_status!=Z_OK){//	error
					printf("inflate error:%d\n",inflate_status);
				//该message解压出错，跳到下个message
				//或者得重新初始化了?
					continue;
				}
				//	解压缩后数据写入z_inflated_db
				add_data(&z_inflate_db,z_inflate_char_tmp,1024-ws_zs_recv.avail_out);
			//判断输入数据是否完整压缩
			}while(ws_zs_recv.avail_out==0);
			//	一个完整的websocket解压缩后message压入队列
			add_ws_data(sys_ws_data_queue_inflated,&z_inflate_db);
			//重新初始化临时变量
			data_buffer_reset_16k(&z_inflate_db);
			data_buffer_reset_16k(&ws_db_tmp);
		}


		//***********************************************************************************
		//	所有队列里的数据都解压完成
		//	清空sys_ws_data_queue_inflated队列,业务相关
		//	从接收到的数据中提取调度单的信息，再判断是否是是历史调单
		//	历史调单无操作，新调单加入sys_order_id_unread队列
		//***********************************************************************************
		//	以下代码业务相关,处理不同类型的websocket MESSAGE
		//***********************************************************************************
		//	2024-03-06 发送数据不支持设置 per-message compressed 位
		json_str_len=0;				//json数据长度
		json_str_begin=NULL;			//json数据开始的地址
		json_str_ptr=NULL;			//存放转义后的json数据
		data_buffer_reset_16k(&ws_db_tmp);	//先清空数据再使用
		while(out_ws_data(sys_ws_data_queue_inflated,&ws_db_tmp)){
		//ws_db_tmp的数据是服务器发送的未压缩的完整message
			//websocket通信开始后服务器会发送一个'o'字符
			//接收到 'o' 代表通信开始
			if ( strncmp(ws_db_tmp.contentPtr,"o",1) == 0 ){
				printf("receive 'o'\n");
				//通信开始后向服务器发送该字符串，可以申请获得调度令提示的信息
				curl_ws_send(ws_handle,WS_SEND_DATA_2,strlen(WS_SEND_DATA_2),\
						&ws_data_send,0,CURLWS_TEXT);
			}
			//调度令提示MESSAGE
			else if ( strncmp(ws_db_tmp.contentPtr,"a[\"MESSAGE\\ndestination:"
					"/topic/oprtOrder",40) == 0 ){
				json_str_begin=find_match_json_string(&ws_db_tmp,"{\\\"receive\\\":[",&json_str_len);
				if(json_str_begin==NULL){
					printf("\n%s\n",ws_db_tmp.contentPtr);
					printf("\nbig problem\n");
					continue;
				}
				// 	删除转义字符'\',记得free
				json_str_ptr=kill_slash_before_double_quote(json_str_begin,json_str_len);
				struct order_page_node *order_pages_tmp;
				order_pages_tmp=order_pages_init();
				get_order_pages_from_json(json_str_ptr,order_pages_tmp);
				//删除重复接收到的id,将新的调度令id加入到unread /history队列
				struct order_page op;
				while(out_order_pages(order_pages_tmp,&op)){
					//已经在sys_order_id_history里的id不处理
				 	if(value_in_queue(sys_order_id_history,op.tb_order_id)){
					}
					else{
						printf("id not in sys_history :%u\n",op.tb_order_id);
				 		in_queue(sys_order_id_history,op.tb_order_id);	
						add_order_pages(sys_order_id_unread,&op);
					}
					order_page_destroy(&op);
				}
				order_pages_destroy(order_pages_tmp);
				free(json_str_ptr);
			}
			/*else if (){
			}	//还可以加入其他数据的处理
			*/
			else{
				printf("\n%s\n",ws_db_tmp.contentPtr);
				printf("收到程序没有处理的websocket信息\n");
			}
			data_buffer_reset_16k(&ws_db_tmp);
		}
		//data_buffer_reset_16k(&ws_db_tmp);

		//***************************************************************************************
		//	至此，处理完了在队列中的所有websocket message
		//	需要提取详细信息的调度单的id已经在sys_order_id_unread里了
		//	根据得到的id值，发送http请求，从web服务器返回
		//	的html页面中提取调度令的详细信息，压入调度单详细信息(sys_order_pages)
		//	队列,报错后将写入/log/iderrors文件
		//***************************************************************************************

		pthread_t http_thread_t;
		struct http_thread_arg *hta;
		struct order_page op;
		while(	out_order_pages(sys_order_id_unread,&op	)){
printf("html pop id:%d\n",op.tb_order_id);
			hta=malloc(sizeof(struct http_thread_arg));
			hta->curl=handle;
			hta->page_info=op;
			pthread_create(&http_thread_t,NULL,http_thread_proc,hta);
			//销毁op后hta->page的orders任然指向调度零队列
			//order_page_destroy(&op);
		}



		//***************************************************************************************
		//	数据库故障，待写入数据库文件是否为空？
		//***************************************************************************************






		//**********************************************************************************
		//	开始清空调度令详细信息队列
		//	将调度令详细信息写入数据库
		//**********************************************************************************
		sys_order_pages_empty=true;
		order_page_init(&op_tmp);
		//	调度令队列是否有数据？
		////	该变量在其他线程有写操作
		order_page_destroy(&op_tmp);
		pthread_mutex_lock(&sys_pages_lock);
		if(out_order_pages(sys_order_pages,&op_tmp)){
			sys_order_pages_empty=false;
		}
		pthread_mutex_unlock(&sys_pages_lock);
		while(!sys_order_pages_empty){
			//	先查询是否重复写入
			sprintf(sql_stat,"%s%llu","select tb_order_id from test_db.tb_order "
					"where tb_order_id=",op_tmp.tb_order_id);
			printf("%s\n",sql_stat);
			query_status=mysql_query(con,sql_stat);
			query_result=mysql_store_result(con);
			row_number=mysql_num_rows(query_result);
			mysql_free_result(query_result);
			if(query_status!=0){
				printf("%s\n",mysql_error(con));
				//数据库连接故障，直接跳到故障处理部分
				//order_page_destroy(&op_tmp);
				//order_page_init(&op_tmp);
				goto DB_EXCEPTION_HANDLE;
			}
			if(row_number>0){//已经在数据库中存在了，无需再添加
				printf("fuck db1\n");
				sys_order_pages_empty=true;
				order_page_destroy(&op_tmp);
				//order_page_init(&op_tmp);
				pthread_mutex_lock(&sys_pages_lock);
				if(out_order_pages(sys_order_pages,&op_tmp)){
					sys_order_pages_empty=false;
				}
				pthread_mutex_unlock(&sys_pages_lock);
				continue;	//跳到while
			}
			//开始写入tb_order表，构造sql语句
			sprintf(sql_stat,"insert into tb_order (tb_order_id,order_year,order_code,"
				"station_id,send_date,receive_date) values (%lu,%u,'%s','%s','%s','%s')",\
				op_tmp.tb_order_id,op_tmp.order_year,op_tmp.order_code,op_tmp.station_id,\
				op_tmp.send_date,op_tmp.recv_date);
			printf("%s\n",sql_stat);
			query_status=mysql_query(con,sql_stat);
			query_result=mysql_store_result(con);
			mysql_free_result(query_result);
			if(query_status!=0){
				//order_page_destroy(&op_tmp);
				goto DB_EXCEPTION_HANDLE;
				//数据库连接故障，直接跳到故障处理部分
			}
			struct order_page op1;
			duplicate_order_page(&op1,&op_tmp);	//no use to init op1
//print_order_page(&op1);
			memset(&order_info,0,sizeof(struct order_info));
			while(out_orders(op1.orders,&order_info)){
				//	don't forget to !!!!!!!!
				//	handle the NULL parameter
				sprintf(sql_stat,"insert into order_info (tb_order_id,order_id,operate,"
				"start_date,end_date,start_time,end_time,days,order_type_name,order_type,"
				"channel,antenna_prog_id,freq,azimuth,actual_power,op_status,trans_name,"
				"ant_used_code,reason,station_name,prog_desc,program_name,ant_prog_desc,"
				"feedback_status,actual_start,modu) values(%lu,%lu,'%s','%s','%s','%s','%s',"
				"'%s','%s','%s','%s',%d,%d,'%s','%s','%s','%s','%s','%s','%s','%s','%s',"
				"'%s','%s','%s','%s')",order_info.tb_order_id,order_info.id,order_info.operate,\
				order_info.start_date,order_info.end_date,order_info.start_time,order_info.end_time,\
				order_info.days,order_info.order_type_name,order_info.order_type,order_info.channel,\
				order_info.antenna_prog_id,order_info.freq,order_info.azimuth,order_info.actual_power,\
				order_info.op_status,order_info.trans_name,order_info.ant_used_code,order_info.reason,\
				order_info.station_name,order_info.prog_desc,order_info.program_name,order_info.ant_prog_desc,\
				order_info.feedback_status,order_info.actual_start,order_info.mod);
				printf("sql statememt\n\n\n");
				printf("%s\n",sql_stat);
				query_status=mysql_query(con,sql_stat);
				query_result=mysql_store_result(con);
				mysql_free_result(query_result);
				if(query_status!=0){
					order_page_destroy(&op1);
					memset(&order_info,0,sizeof(struct order_info));
					goto DB_EXCEPTION_HANDLE;
					//数据库连接故障，直接跳到故障处理部分
				}
				memset(&order_info,0,sizeof(struct order_info));
			}
			order_page_destroy(&op_tmp);
			order_page_destroy(&op1);
			sys_order_pages_empty=true;
			//	再读取调度单详细信息队列数据
			pthread_mutex_lock(&sys_pages_lock);
			if(out_order_pages(sys_order_pages,&op_tmp)){
				sys_order_pages_empty=false;
			}
			pthread_mutex_unlock(&sys_pages_lock);
			continue;	//跳转到while
DB_EXCEPTION_HANDLE:
			//数据库故障处理部分
			printf("write db failed %d\n",op_tmp.tb_order_id);
			printf("error:%s\n",mysql_error(con));
			char filename[30];
			sprintf(filename,"./db_error/%u",op_tmp.tb_order_id);
			order_page_to_file(&op_tmp,filename);
			order_page_destroy(&op_tmp);
			//order_page_init(&op_tmp);
			sys_order_pages_empty=true;
			pthread_mutex_lock(&sys_pages_lock);
			if(out_order_pages(sys_order_pages,&op_tmp)){
				sys_order_pages_empty=false;
			}
			pthread_mutex_unlock(&sys_pages_lock);
		}
		order_page_destroy(&op_tmp);


		//**********************************************************************
		//	定时清理历史调度单号队列
		//**********************************************************************
		static unsigned long just_delay=0;
		//	每xxx查看一次调度单号历史队列
		if( (just_delay++)%86400==0 ){
			int page_count=int_queue_count(sys_order_id_history);
			if(page_count>=1100){
				int num_to_destroy=page_count-1100;
				int order_id;
				while(num_to_destroy--){
					out_queue(sys_order_id_history,&order_id);
				}
			}
		}
		//	检查网络状态是否正常,网络故障跳转到初始化
		if ( just_delay%300 == 0 ){
			pthread_t net_check;
			struct net_thread_arg *arg=malloc(sizeof(struct net_thread_arg));
			arg->curl=handle;
			strcpy(arg->cookies,jsessionid_ptr);
			strcat(arg->cookies,"; ");
			strcat(arg->cookies,remember_ptr);
			strcat(arg->cookies,";");
			pthread_create(&net_check,NULL,net_check_proc,arg);
		}
		//	打印history信息
		if( just_delay%20==0 ){
			printf("sys order id in history: \n");
			struct int_queue_node *t=sys_order_id_history;
			int cr=0;
			while(t->next!=NULL){
				if( (cr++)%10 == 0 )printf("\n");
				printf("%d ",t->next->node_value);
				t=t->next;
			}
			printf("\n");
		}
		//检查网络状态
		bool status;
		pthread_mutex_lock(&net_status_lock);
		status=net_status;
		pthread_mutex_unlock(&net_status_lock);
		if(status==false){
			curl_easy_cleanup(handle);
			curl_easy_cleanup(ws_handle);
			goto SYS_START;
		}






	}	//while(1)
	//******************************************************************************
	//	http cleanup
	//*****************************************************************************
	//curl_slist_free_all(request_header);
	//curl_easy_cleanup(handle);
	//curl_global_cleanup();
	//******************************************************************************
	


WEBSOCKET_ERROR:
	mysql_close(con);
	inflateEnd(&ws_zs_recv);
	curl_easy_cleanup(handle);
	curl_easy_cleanup(ws_handle);
	curl_global_cleanup();		    		    //libcurl环境初始化 only once
	order_pages_destroy(sys_order_pages);	    	    //调度令信息队列初始化
	order_pages_destroy(sys_order_id_unread);	    //未读取信息队列初始化
	destroy_int_queue(sys_order_id_history);	    //已读取详细信心的调度令id队列
	ws_data_queue_destroy(sys_ws_data_queue_deflated);    //初始化解压缩前数据队列
	ws_data_queue_destroy(sys_ws_data_queue_inflated);    //初始化解压缩后数据队列
	pthread_mutex_destroy(&sys_pages_lock);	    //初始化共享锁
	pthread_mutex_destroy(&error_file_lock);	    //初始化共享锁
	pthread_mutex_destroy(&net_status_lock);	    //初始化共享锁
	//*****************************************************************************************
	//	局部变量初始化
	//*****************************************************************************************
	data_buffer_destroy(&http_cb_arg);
	data_buffer_destroy(&http_hd_cb_arg);
	data_buffer_destroy(&ws_db_tmp);	//初始化ws通信接收数据缓存
	data_buffer_destroy(&z_inflate_db);

	return 0;
}	//main

//***********************************************************************
//	main.c 函数http响应回调函数
//***********************************************************************
size_t http_cb_func(char *text,size_t size,size_t nmemb,void* arg){
	struct data_buffer *db=(struct data_buffer*)arg;
	add_data(db,text,nmemb);
	return size*nmemb;
}

size_t http_hd_cb_func(char *text,size_t size,size_t nmemb,void* arg){
	struct data_buffer *db=(struct data_buffer*)arg;
	add_data(db,text,nmemb);
	return size*nmemb;
}

size_t http_body(char *text,size_t size,size_t nmemb,void* arg);
size_t http_header(char *text,size_t size,size_t nmemb,void* arg);


//****************************************************************************
//	网络状态检查线程
//****************************************************************************
void * net_check_proc(void *argumeng){
	pthread_detach(pthread_self());
	struct net_thread_arg * arg=argumeng;
	CURL *handle=curl_easy_duphandle(arg->curl);
	CURLcode code;
	struct curl_slist *header=NULL;
	char url[128];
	char cookies[1024];
	char post_data[64];
	int exception_retry_times;
	strcpy(cookies,arg->cookies);
	//*********************************************************************************
	//	http2请求参数设置 获取调度令详细信息
	//*********************************************************************************
	//	url
	sprintf(url,"http://%s/oprt-order-op/oprt-order-op-list-load.action?id=%d","10.12.3.23",120998);
	curl_easy_setopt(handle,CURLOPT_URL,url);
	//	post method
	curl_easy_setopt(handle,CURLOPT_POST,1L);
	curl_easy_setopt(handle,CURLOPT_TIMEOUT,20L);
	curl_easy_setopt(handle,CURLOPT_CONNECTTIMEOUT,20L);
	//	http post data
	strcpy(post_data,"_search=false&nd=170674596366&rows=10&page=1&sidx=&sord=asc");
	curl_easy_setopt(handle,CURLOPT_POSTFIELDS,post_data);
	curl_easy_setopt(handle,CURLOPT_POSTFIELDSIZE,strlen(post_data));
	//	http header
	header=NULL;
	header=curl_slist_append(header,"Accept: */*");
	header=curl_slist_append(header,"Accept-Encoding: gzip, deflate");
	header=curl_slist_append(header,"Content-Type: application/x-www-form-urlencoded");
	curl_easy_setopt(handle,CURLOPT_HTTPHEADER,header);
	//	http cookie
	//strcpy(cookies,jsessionid_ptr);
	//strcat(cookies,"; ");
	//strcat(cookies,remember_ptr);
	//strcat(cookies,";");
	curl_easy_setopt(handle,CURLOPT_COOKIE,cookies);
	//	callback function
	curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,http_body);
	curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,http_header);
	curl_easy_setopt(handle,CURLOPT_WRITEDATA,NULL);
	curl_easy_setopt(handle,CURLOPT_HEADERDATA,NULL);
	//***********************************************************************************
	//	send http request
	//***********************************************************************************
	exception_retry_times=6;
	while(exception_retry_times--){
		code=curl_easy_perform(handle);
		if(code==CURLE_OK){
			long response_code;
			curl_easy_getinfo(handle,CURLINFO_RESPONSE_CODE,&response_code);
			if( response_code == 200 ){
				break;
			}
		}else{
		}
	}
	free(arg);
	curl_easy_cleanup(handle);
	curl_slist_free_all(header);
	if(exception_retry_times==-1){
		printf("net error\n");
		pthread_mutex_lock(&net_status_lock);
		net_status=false;
		pthread_mutex_unlock(&net_status_lock);
	}else{
		printf("net ok\n");
		pthread_mutex_lock(&net_status_lock);
		net_status=true;
		pthread_mutex_unlock(&net_status_lock);
	}
	pthread_exit(NULL);
	return NULL;
}

//***********************************************************************
//	net_check_proc函数http响应回调函数
//***********************************************************************
size_t http_body(char *text,size_t size,size_t nmemb,void* arg){
	//struct data_buffer *db=(struct data_buffer*)arg;
	//add_data(db,text,nmemb);
	return size*nmemb;
}

size_t http_header(char *text,size_t size,size_t nmemb,void* arg){
	//struct data_buffer *db=(struct data_buffer*)arg;
	//add_data(db,text,nmemb);
	return size*nmemb;
}

//	int len;
//	char c;
//	if(src==NULL)return;
//	len=strlen(src);
//	for(int i=0;i<len;i++){
//		if(c!='\r' && c!='\n')
//			*dst=*src;
//	}
//}

//int test_main(){
//	/*
//	//char *target="a[\"MESSAGE\\ndestination:/topic/oprtOrder\\ncontent-type:application/json;charset=UTF-8\\nsubscription:sub-6\\nmessage-id:zu109d70-901315695\\ncontent-length:28\\n\\n{\\\"receive\\\":[],\\\"feedBack\\\":[]}\\u0000\\\"]";
//	//char *target="[\"SUBSCRIBE\\nid:sub-6\\ndestination:/topic/oprtOrder\\n\\n\\u0000\"]";
//	//char *find_json_string(struct data_buffer *input,char *noodle,int *strlen){
//	char target[20000];
//	FILE *fp=fopen("result.txt","r");
//	fread(target,1,20000,fp);
//	struct data_buffer db;
//	data_buffer_init_16k(&db);
//	add_data(&db,target,strlen(target));
//	size_t len;
//	char *ret=find_match_json_string(&db,"{\\\"receive\\\"",&len);
//	if(ret==NULL){printf("fuck\n");}
//	else
//		printf("%.*s\n",len,ret);
//	*(ret+len)='\0';
//	char *tmp=kill_slash_before_double_quote(ret,len);
//	printf("%s\n",tmp);
//	free(tmp);
//	fclose(fp);
//	return 0;
//	*/
//	struct order_page op;
//	struct order_info info;
//	order_page_init(&op);
//	//-----------------------------------------------
//	op.tb_order_id=122334455;
//	op.order_year=2024;
//	strcpy(op.order_code,"01343456");
//	strcpy(op.station_id,"78");
//	strcpy(op.send_date,"2024-03-09 13:20:20");
//	strcpy(op.recv_date,"2024-03-09 13:22:20");
//	//-----------------------------------------------
//	info.id=1234567;
//	info.tb_order_id=122334455;
//	strcpy(info.operate,"1");
//	strcpy(info.start_date,"2024-03-03");
//	strcpy(info.end_date,"2024-03-23");
//	strcpy(info.start_time,"21:00:00");
//	strcpy(info.end_time,"22:30:00");
//	strcpy(info.days,"34");
//	strcpy(info.order_type_name,"实验");
//	strcpy(info.order_type,"I");
//	strcpy(info.channel,"54");
//	info.antenna_prog_id=146;
//	info.freq=18640;
//	strcpy(info.azimuth,"352");
//	strcpy(info.actual_power,"50");
//	strcpy(info.op_status,"32");
//	strcpy(info.trans_name,"A04");
//	strcpy(info.ant_used_code,"104");
//	strcpy(info.station_name,"2023台");
//	strcpy(info.prog_desc,"146(HR2/2/0.5)");
//	strcpy(info.program_name,"中一");
//	strcpy(info.ant_prog_desc,"HR2/2/0.5");
//	strcpy(info.feedback_status,"90");
//	strcpy(info.actual_start,"2024-03-04 11:22:33");
//	strcpy(info.mod,"D");
//	add_orders(op.orders,&info);
//	//-------------------------------------------
//	memset(&info,0,sizeof(struct order_info));
//	info.id=123321333;
//	info.tb_order_id=99999999;
//	strcpy(info.operate,"1");
//	strcpy(info.start_date,"2024-03-03");
//	strcpy(info.end_date,"2024-03-23");
//	strcpy(info.start_time,"21:00:00");
//	strcpy(info.end_time,"22:30:00");
//	strcpy(info.days,"34");
//	strcpy(info.order_type_name,"实验");
//	strcpy(info.order_type,"I");
//	strcpy(info.channel,"70");
//	info.antenna_prog_id=269;
//	info.freq=6180;
//	strcpy(info.azimuth,"352");
//	strcpy(info.actual_power,"50");
//	strcpy(info.op_status,"32");
//	strcpy(info.trans_name,"A04");
//	strcpy(info.ant_used_code,"104");
//	strcpy(info.station_name,"2023台");
//	strcpy(info.prog_desc,"146(HR2/2/0.5)");
//	strcpy(info.program_name,"中一");
//	strcpy(info.ant_prog_desc,"HR2/2/0.5");
//	strcpy(info.feedback_status,"90");
//	strcpy(info.actual_start,"2024-03-04 11:22:33");
//	strcpy(info.mod,"D");
//
//	//add_orders(op.orders,&info);
//	//add_orders(op.orders,&info);
//	//print_order_page(&op);
//	if(order_page_to_file(&op,"122334455")){
//		printf("OK\n");
//	}
//	//else
//	//	printf("failed\n");
//	order_page_destroy(&op);
//
//	//order_page_init(&op);
//	//if(order_page_from_file(&op,"122334455")){
//	//	printf("OK\n");
//	//}
//	//else
//	//	printf("failed\n");
//	//print_order_page(&op);
//	//order_page_destroy(&op);
//}
